package umls.Metamap;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.xml.namespace.QName;

import metamap.proxy.server.jaxws.MetamapProxyService;
import metamap.proxy.server.jaxws.MetamapService;

import org.apache.log4j.Logger;

public class MetamapClient {
        private static ExecutorService executor;
        private URL url;
        MetamapProxyService service;
        static MetamapService port;
        static Logger logger = Logger.getLogger(MetamapClient.class);
        public MetamapClient(String service_adress) throws MalformedURLException {
                url = new URL(service_adress);
                String wsdlname = url.getFile();
                if (wsdlname.equals("") || wsdlname == null) {
                        System.out.println(service_adress + " non è valido");
                        System.exit(2);
                }
                service = new MetamapProxyService(url, new QName(
                                "http://jaxws.server.proxy.metamap/",
                                "MetamapServiceImplService"));
                port = service.getMetaMapPort();
                executor = Executors.newFixedThreadPool(20);
        }
/**
 * Blocking method that retrieve the preferred names from the service
 * @param term The text to get mapped
 * @return a List<String> containing the preferred names
 */
        public static  List<String> blockingQuery(String term,List<String> gruppi) {

                List<String> output = port.getPreferredNames(term, gruppi);
               logger.trace("a blocking query done with "+ output.size()+" results");
                return output;

        }
/**
 * This method provides a way to asynchronously call the metamap service,
 * using a worker thread. Each instance of MetamapClient share the same limit of
 * thread, this method will block this limit is reached
 * the Future will contain the result
 * @param text The text to get meta-mapped
 * 
 * @return a Future of List<String> containing the results
 */
        public  Future<List<String>> delayedQuery(String text,List<String> gruppi) {
        		
                Worker w = new Worker(text, gruppi);
                Future<List<String>> out = executor.submit(w);
                return out;
        }
}
/**
 * Worker class used by the MetamapClient, each instance is executed in a separated thread
 * @author melo
 *
 */
class Worker implements Callable<List<String>> {
        private String text;
        private List<String> gruppi;
        public Worker(String s, List<String> g) {
                text = s;
                gruppi=g;
                
        }

        public Worker(BufferedReader br) {
                String line;
                StringBuffer result = new StringBuffer();
                try {
                        while ((line = br.readLine()) != null) {
                                result.append(line);
                        }
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                text = result.toString();
        }

        @Override
        public List<String> call() {
                return MetamapClient.blockingQuery(text, gruppi);

        }

}
